from CommandWriter import *
from StateReader import *
from LifeLike import *
from Elementary import *
#from ReadFlags import *
from tkinter import *
from tkinter.filedialog import askopenfilename
import os
import subprocess
import threading
import operator
import time
import shutil

#Called in the very beginning. Cleans up any 
#files that we use that may already exist
def initialFileCheck():
	if os.path.isfile("flag.txt"):
		os.remove("flag.txt")
	if os.path.isfile("rules.txt"):
		os.remove("rules.txt")
	if os.path.isfile("ruletype.txt"):
		os.remove("ruletype.txt")
	MakeEmptyFile('commands.txt')
	CleanDir('states')

#Determines what automata we're using, creates its
#window and the polling thread	
def StartGUI(root, ruleNum):
	
	cellularGui = None
	
	if ruleNum == 0:
		cellularGui = Elementary(root)
	elif ruleNum == 1:
		cellularGui = LifeLike(root)
	
	pollThread = threading.Thread(target=PollForUpdates, args=[cellularGui, ruleNum])
	pollThread.setDaemon(True)
	pollThread.start()
	
	root.update()
	root.deiconify()
	root.mainloop()

#Keep the file but make it empty
def MakeEmptyFile(filename):
	if os.path.isfile(filename):
		os.remove(filename)

	file = open(filename, 'w')
	file.write('')
	file.close()

#Keep the directory but empty it
def CleanDir(dirname):
	if os.path.exists(dirname):
		shutil.rmtree(dirname)
	os.makedirs(dirname)

#The main update loop that manages keeping the gui up to date
#cellularGui is an instance of either Lifelike.py or
#Elementary.py
def PollForUpdates(cellularGui, ruleNum):
	
	generation = 0
	filename = "states/statefile_" + str(generation) + ".txt"
	
	while True:
	
		if os.path.isfile(filename) == True:
			updates = ReadFullFile(filename)
			if updates == '':
				print('skipped update, empty')
				#try again when ACL2 might have had time to write it
				continue

			if ruleNum == 0:	
				try:
					coords = ParseElementaryState(updates, generation)
				except ValueError:
					continue
			elif ruleNum == 1:
				try:
					coords = ParseLifeLikeState(updates, generation)
				except ValueError:
					continue
			
			DeleteFile(filename)
			
			cellularGui.handleACL2Coordinates(set(coords))
			
			#If the pan block is set, redraw with the new shifts
			if cellularGui.panBlock == True:
				cellularGui.clearGui()
				cellularGui.updateGui()
				cellularGui.panBlock = False
				
			generation += 1
			
			filename = "states/statefile_" + str(generation) + ".txt"
			
		time.sleep(.05)

class GuiUpdateDriver:
	#make sure we kill the acl2 process when we close
	def goodbye(self):
		self.acl2process.terminate()
		self.root.destroy()
		
	def __init__(self):
		self.root = Tk()
		self.root.withdraw()
		
		initialFileCheck()

		filename = askopenfilename(title = "Please Select a Rule File to Use", filetypes = [("XML", '.xml')])
		WriteConfigFilename(filename)

		self.acl2process = subprocess.Popen("build.exe")
		self.root.protocol('WM_DELETE_WINDOW', self.goodbye)

		#Wait until we find a ruletype response from ACL2S
		ruleNum = None
		count = 1
		while (True):
			if os.path.isfile("ruletype.txt"):
				rule = ReadFullFile("ruletype.txt")
				
				if rule == "elementary":
					ruleNum = 0
				elif rule == "lifelike":
					ruleNum = 1
				break
			
			count += 1
			if count % 50 == 0:
				print("looking for ruletype.txt... make sure build.exe exists and hasn't crashed!")
			time.sleep(.01)

		
		
		StartGUI(self.root, ruleNum)


if __name__ == '__main__':
	GuiUpdateDriver()